///////////////////////////////////////////////////////////////////////
//                                                                   //
// KconfigSize : Linux kernel size and memory usage measurement tool //
// target-config-item list and tool configuration                    //
//                                                                   //
///////////////////////////////////////////////////////////// /////////

Introduction
============================================================
In this document, below contents will be described:
- two measurement approaches
- target list of config items in top-down approach
- target list of config items in bottom-up  approach
- tool configuration file

Two measurement approaches 
===========================================================
KconfigSize tool is used to measure the size and memory usage of each config 
item. There are two approaches to perform measurement. 

(1) top-down approach
-----------------------
Based on .config file created by user, impact towards the size and memory usage
of enabled config items (=y or =m) can be measured. Config items are specified 
in target-config-item list. So, in top-down approach, target-config-items are
specified by: 
  -- base .config file 
  -- target config list 
By top-down approach, cutting which part can cause the reduction of size/memory
 usage can be understood clearly. 

In top-down approach, KconfigSize tool will run like below: 
KconfigSize tool can disable the specified config item in base .config file, 
and then generate the new .config file. Theoretically, the number of generated 
.config file is the number of target-config-items plus 1.[+1] means the base
 .config file. All these .config files are built with the help of kernel 
source, and kernel images can be generated. By measuring each kernel image, 
the size and memory usage of each kernel can be measured. The kernel built by
base .config file is called "base kernel".
By subtracting data(size and memory usage) of each kernel and base kernel, 
impact of each config item can be measured.  

In this process, the dependency of config item is handled automatically. 
For exmaple, CONFIG_A depdends on CONFIG_B, in base .config file, 
CONFIG_A=y, CONFIG_B=y. If CONFIG_B is specified as the target-config-item, 
then KconfigSize tool will change CONFIG_B=n. But if CONFIG_A=y, there is 
error since CONFIG_A depends on CONFIG_B. So KconfigSize tool will make 
CONFIG_A=n, too. In the end, both CONFIG_A and CONFIG_B are disabled. 

In top-down approach, it is possible that even the base kernel can not boot. 
Under such circumstance, the memory measurement fails. 

(2) bottom-up approach
------------------------
In target-config-item list, below contents should be specified to measure the 
isolated impact of size/memory usage.
  - config items enabled (CONFIG_*=y) all the time
  - config items for measurement

Ordinary, some config items must be enabled (CONFIG_*=y) all the time, because 
without these items, the kernel can not boot at all. They are the basic config 
items to make kernel boot, so they are always enabled. 
In bottom-up approach, .config file is not used as the input information. All 
the .config files are generated from the target list automatically. 

bottom-up approach is suitable for comparing the data trend of a specific 
config item over different kernel versions. The reason is that in bottom-up 
approach, the "isolated impact" of config item can be calculated. 
(For isolated impact, please refer to later parts). However, the basic 
config items for boot change over kernel versions, target-config-item list 
should be adjusted to some extent by kernel versions.

In bottom-up approach, KconfigSize tool runs like below: 
KconfigSize tool will first generate the base .config file based on those 
always enabled config items. Then by using base .config file, one config item 
for measurement is enabled (CONFIG_*=y) one at a time, and a new .config file 
is generated. 

So the number of generated .config file is the number of target-config-items 
plus 1.[+1] means the base .config file. 
All these .config files are built with the help of kernel source, and kernel 
images can be generated. By measuring each kernel image, the size and memory 
usage of each kernel can be measured.  The kernel built by base .config file is
called "base kernel". By subtracting data(size and memory usage) of each 
kernel and base kernel, isolated impact of each config item can be measured.  

Bottom-up approach should handle the problem of dependency just as top-down 
approach. But their direction is different. Top-down approach will disable 
those config items which depend on target-config-item, while bottom-up approach
will enable those config items which target-config-item depends on. 

As a result, the impact includes the parts of those config items which the
target-config-item depends on. So, KconfigSize tool will try to clear out the
influence of those config items and get the "isolated impact", which is the
impact of that single target-config-item alone.
The method is as below: 

Now assume that CONFIG_X is the target-config-item, and CONFIG_X depdends on
CONFIG_Y. 
KconfigSize tool handles the dependency automatically, so CONFIG_X and CONFIG_Y
is set to =y and generate the .config file and kernel for the examination of
CONFIG_X. (x)
On the other hand, if CONFIG_Y is the target-config-item, then .config file
with CONFIG_X=n and CONFIG_Y=y is generated for CONFIG_Y, and built a kernel. (y)
So KconfigSize tool can calculate the isolated impact of CONFIG_X by
substracting the size of kernel(y) from the size of kernel(x).

Although KconfigSize tool tries to calculate the isolated impact, if CONFIG_Y
is not set as the target-config-item, the isolated impact of CONFIG_X can not
be calculated. In such situation, the impact of CONFIG_X will be recorded in the
form of [CONFIG_X+CONFIG_Y] to result file. The value is the size of kernel of
CONFIG_X minus the size of base kernel. 

From the above method, bottom-up approach has below draw-backs:
-  need adjust target-config-items over kernel versions
-  in order to calculate the isolated impact of all target-config-items, 
   target-config-item list should be set carefully. 

So, it is recommended that bottom-up approach should be used only under
necessary circumstances. 

Target-config-item list in top-down approach
============================================================
target-config-item list in top-down approach is very simple. Basically, one 
target-config-item occupies just one line. These config items must be enabled
in base .config file. 

--- target-config-item list example(top-down approach) ---
CONFIG_NTFS_FS
CONFIG_ISO9660_FS
CONFIG_USB
CONFIG_INET
MENU TCP/IP networking

Target-config-items can be specified by two methods.
-config symbol name(CONFIG_*)
  such as "CONFIG_NTFS_FS", "CONFIG_INET" etc in above example. 
-Kconfig prompt string
  "MENU" prefix plus Kconfig prompt string, such as "MENU TCP/IP networking"
  in above example.
  "MENU" is the prefix and "TCP/IP networking" is the prompt string of
  CONFIG_INET. So, actually "CONFIG_INET" and "MENU TCP/IP networking" has the
  same meaning. 
  (of course, ordinary the same config item will not be specifed by two means, 
   it is just an example.)
  
  Using MENU keyword, you can measure the impact of item without symbol like
  CONFIG_*. For example, if "MENU Ethernet (10 or 100Mbit)" is specified,
  the size/memory impact of all config items which appear under the menu of
  "Ethernet (10 or 100Mbit)" during [make menuconfig] can be measured. 
  (If multiple drivers are enabled in the base .config file, the impact of
   each single driver will be summarized and recorded to result.)
   
If an item which is disabled (CONFIG_*=n) in the base .config file is specified,
the impact measurement of this config item is regarded as failure.

Target-config-item list in bottom-up  approach
============================================================
in bottom-up approach , the target-config-item list can be specified as below: 
- always enabled (CONFIG_*=y) config item
    mark as =b 
- target-config-item
    mark as =f

--- target-config-item list example (bottom-up approach) ---
CONFIG_MPENTIUMM=b
CONFIG_MMU=b
CONFIG_SWAP=f
CONFIG_MTD=f
CONFIG_INET=f

CONFIG_MPENTIUMM and CONFIG_MMU are config items always enabled. So they are 
marked as =b. CONFIG_SWAP, CONFIG_MTD, and CONFIG_INET are target-config-items,
so they are marked as =f.

Based on this list,  four .config file and kernel are generated like below: 
CONFIG \ No|  0 |  1 |  2 |  3 
-------------------------------
MPENTIUMM  | =y | =y | =y | =y 
MMU        | =y | =y | =y | =y 
SWAP       | =n | =y | =n | =n 
MTD        | =n | =n | =y | =n 
INET       | =n | =n | =n | =y 

No.0 : base kernel
No.1 : kernel for CONFIG_SWAP measurement
No.2 : kernel for CONFIG_MTD measurement
No.3 : kernel for CONFIG_INET measurement
In fact, there are other config items depended by target-config-item are
enabled but just omit them here for simplicity.

Tool configuration file
============================================================
Tool configuration file is used to tell how KconfigSize tool runs. The 
top-level command of KconfigSize tool is "kconfigsize", this command will 
accept tool configuration file as parameter. 

The format of tool configuration file is : <key>=<value>
One key and value pair occupies a single line. 

If value is specified as relative path, then it is relative to the TESTROOT. 
For example, if TESTROOT=/home/foo/kconfigsize, then WORK_PATH=../tmp is the 
same as WORK_PATH=/home/foo/tmp .

A line starts with "#" is for comment purpose. 

All keys are explained like below.
If specifed [can be omitted], then the value in later brace means the default 
value.

TESTROOT=<value>
------------------------------
  Need specify: must
  Top directory path of KconfigSize tool must be specified using absolute path.
Example: 
    TESTROOT=/home/foo/tools/kconfigsize

TEST_NAME=<value>
------------------------------
  Need specify: must
  Describe the measurement name, for below purpose. 
    - DB file name(output in the end) 
      (refer to DB_PATH)
    - temporary output directory name 
      (refer to WORK_PATH)

DB_PATH=<value>
------------------------------
  Need specify: can be omitted(TESTROOT)
  Specify output directory for generated db file. If specified directory does 
  not exist, create accordingly. 
  Example: 
      TEST_NAME=test_2.6.8
      DB_PATH=/home/foo/dbs
  DB file will be generated as below
      /home/foo/dbs/test_2.6.8_{td|bu}.db
    {td|bu} :  "td" means top-down approach, "bu" means bottom-up approach

WORK_PATH=<value>
------------------------------
  Need specify: can be omitted(TESTROOT)
  Specify output directory for temporary generated files. If specified 
  directory does not exist, create accordingly.
  Example: 
      TEST_NAME=test_2.6.8
      WORK_PATH=/home/foo/tmp
  All the temporary generated files should output to /home/foo/tmp
... result text file should output to /home/foo/tmp/test_2.6.8/work/
... .config file,kernel image should output to /home/foo/tmp/test_2.6.8/kernel/

KERNEL_CONFIG=<value>
------------------------------
  Need specify: must in top-down approach
                must NOT in bottom-up approach
  Specify the .config file in top-down approach
  KconfigSize tool will judge which approach user want to use by the existence
  of KERNEL_CONFIG.

TARGET_LIST=<value>
------------------------------
  Need specify: must
  Specify target-config-item list file.
  
KERNEL_SOURCE=<value>
------------------------------
  Need specify: must
  Specify kernel source directory.
  Example: 
    KERNEL_SOURCE=/home/foo/kernels/linux-2.6.10

MAKE_TARGET=<value>
------------------------------
  Need specify: must
  Specify the target that kernel want to make, such as bzImage or uImage
  Example: 
    bzImage

CROSS_COMPILE=<value>
------------------------------
  Need specify: can be omitted(null)
  When cross-compile the kernel, specify prefix of the cross compiler
  Example: 
    CROSS_COMPILE=arm-linux-

VERSION=<value>
------------------------------
  Need specify: must
  Specify kernel version

ARCH=<value>
------------------------------
  Need specify: must
  Specify target kernel architecture
  Example: 
    ARCH=i386

MACH=<value>
------------------------------
  Need specify: can be omitted(null)
  Specify target kernel machine name 
  MACH is only used as record. It has nothing to do with kernel making process. 
  Example: 
    MACH=pc

DO_TEST=<value>
------------------------------
  Need specify: must
  Specify measurement type, including: 
    size :  kernel static size
    mem  :  kernel dynamic memory usage
  If both need to be measured, then specify using space as the separator like 
  below:
    DO_TEST=size mem
  
******************************
Under circumstance of [DO_TEST=* mem], below items should be set, too. 
If [DO_TEST=size], just ignore below items. Please refer to docs/target_en.txt
******************************

RESET_HELPER=<value>
------------------------------
  Need specify: must if [DO_TEST=* mem]
  Specify the reset command which can reset the target machine. 
  Example: 
    RESET_HELPER=./bin/local/parallel_reset.sh

  In KconfigSize tree, reset helpers as below are available for example:
    - bin/local/parallel_reset.sh
      bin/local/treset (source: src/treset.c)
        treset is the program which use parallel port to control the power of
        target machine. parallel_reset.sh is the wrapper of treset. 
    - bin/local/kill_qemu.sh
        reset helper when using qemu emulator as the target machine. 

RESET_HELPER_PARAM=<value>
------------------------------
  Need specify: can be omitted(null)
  Specify the parameter passed to reset helper. If there are multiple 
  parameters, use space to separate them. 
  Example: 
    RESET_HELPER_PARAM=./bin/local/treset

MEM_MEASURE=<value>
------------------------------
  Need specify: must if [DO_TEST=* mem]
  Specify the program which communicate with target machine.
  (so called "stream converter")
  Example: 
    MEM_MEASURE=./bin/local/sstream

  In KconfigSize tree, stream converters as below are available for example:
    - bin/local/sstream (source: src/sstream.c)
      The stream converter when target is connected by serial port.

    - bin/local/mem_qemu.sh
      The stream converter when using qemu emulator as the target machine.

MEM_MEASURE_PARAM=<value>
------------------------------
  Need specify: can be omitted(null)
  Specify the parameter passed to stream converter. If there are multiple 
  parameters, use space to separate them. 

  Example: 
    MEM_MEASURE_PARAM=./conf/serial.config

INSTALL_IMAGE=<value>
------------------------------
  Need specify: must if [DO_TEST=* mem]
  Specify the path of kernel image in host machine, target machine will 
  download kernel image from host by this path and boot accordingly. 

MEM_RESULT_KEY=<value>
------------------------------
  Need specify: must if[DO_TEST=* mem]
  Specify the keyword of identifying memory usage result, which is output by 
  target machine.
  KconfigSize tool recognizes a string starting with this keyword as a memory
  usage result.

  Example: 
    MEM_RESULT_KEY=RST

RESET_KEY=<value>
------------------------------
  Need specify: can be omitted(null)
  Specify the keyword of identifying that target machine can be reset now. 
  KconfigSize tool recognizes a string starting with this keyword as a reset
  acceptance.
  Once KconfigSize tool gets memory usage result, it will wait for RESET_KEY. 
  If it gets RESET_KEY, host machine understands that target machine can be 
  reset. Then it will further wait RESET_DELAY seconds and then reset target 
  machine. However, if after RESET_TIMEOUT seconds, RESET_KEY still can not 
  be gotten, then target machine is reset immediately.
  If RESET_KEY is not specified, then after getting memory usage result, 
  it will wait RESET_DELAY seconds unconditionally and reset target machine. 
  Example: 
    RESET_KEY=System halt

RESET_TIMEOUT=<value>
------------------------------
  Need specify: can be omitted(0)
  Specify the time need to wait for RESET_KEY. (unit : seconds)
  If RESET_TIMEOUT passed, and RESET_KEY still does not come out, then target
  machine is reset.
  If RESET_TIMEOUT is not specified, or RESET_TIMEOUT is 0, then it will wait 
  infinitely. 

RESET_DELAY=<value>
------------------------------
  Need specify: can be omitted(0)
  Specify wait time from getting RESET_KEY to actual reset. (unit : seconds)
  If RESET_KEY is not specified, this means wait time from getting memory usage
  result to actual reset.


